#  92: class QT_DEPRECATED_VERSION_X_5_15("Use std::list instead") QLinkedList
# QT_DEPRECATED_VERSION_5_15
# QT_DEPRECATED_VERSION(5, 15)
setTopNodes = set()
class Node:
    def __init__(this, name:str, category:str, parentKeys=[], hint = ''):
        this.name = name
        this.category = category
        this.parentKeys = parentKeys
        this.lstChildren = []
        this.childCnt = 0
        this.descendantCnt = 0
        this.hint = hint


def ParseFile():
    try:
        with open('./in_qt5_classes.txtdat.txt', encoding='UTF-8') as fd:
            data = fd.readlines()
    except:
        with open('./in_qt5_classes.txtdat.txt', encoding='GBK') as fd:
            data = fd.readlines()        
    dctNodes = dict()
    dctCategory = dict()
    sFile = 'xxx.h'
    for (lnNdx, item) in enumerate(data):
        item = item.strip()
        if len(item) < 11 or item.find('//') >= 0:
            continue
        if item.endswith('.h:'):
            sFile = item[:-1]
        ndx = item.find(': class')
        if ndx < 0:
            continue
        if lnNdx == 15086:
            dbg = 0
        ndx += len(': class ')
        item = item[ndx:]
        lstItem = item.split(' ')
        if len(lstItem) < 2:
            continue
        if lstItem[0].find('EXPORT') < 0:
            lstItem = ['QT_UNKNOWN_EXPORT'] + lstItem
        if lstItem[-1] == '{':
            lstItem = lstItem[:-1]

        if lstItem[0].find('(') >= 0:
            # 删除包含带括号的宏修饰
            lstItem = lstItem[1:]            
        parentKeys = []        
        if len(lstItem) >= 3:
            parentKeys = lstItem[2:]
        category = lstItem[0].split('_')[1]
        node = Node(lstItem[1], category, parentKeys, lnNdx)
        node.header = sFile
        if parentKeys == []:
            setTopNodes.add(node)
        dctNodes[lstItem[1]] = node
        try:
            dctCategory[category].append(node)
        except:
            dctCategory[category] = [node]
    # 填充children
    dctMissed = dict()
    for node in dctNodes.values():
        if node.parentKeys == []:
            continue
        for parentKey in node.parentKeys:
            try:
                dctNodes[parentKey].lstChildren.append(node.name)
            except:
                # 找到未定义的类，成为了别人的父类，临时补上
                if not parentKey in dctMissed.keys():
                    newNode = Node(parentKey, node.category, parentKeys=[], hint=node.hint)
                    newNode.lstChildren = [node.name]
                    dctMissed[parentKey] = newNode
                else:
                    dctMissed[parentKey].lstChildren.append(node.name)
                # print(node.hint, node.name, parentKey)
    # 把补上的节点合并
    dctNodes = {**dctNodes, **dctMissed}
    for node in dctMissed.values():
        setTopNodes.add(node)
    bkpt = 0
    return setTopNodes, dctNodes

def GetNameChain(node:Node, dctNode):
    sKey = node.name + '@' + node.category
    if len(node.parentKeys) > 0:
        sKey += ' -> ' + GetNameChain(dctNode[node.parentKeys[0]], dctNode)
    return sKey

def ScanNodes(node:Node, dctNode, indent, prefix = ''):
    chainName = GetNameChain(node, dctNode)
    print(' ' * indent + chainName + ' (%d) ' % (node.descendantCnt))
    for childKey in node.lstChildren:
        node2 = dctNode[childKey]
        ScanNodes(node2, dctNode, indent + 4)


def ScanNodesVerbose(node:Node, dctNode, indent, prefix = ''):
    sOut = prefix + '.' + node.name + ' (%d) ' % (node.descendantCnt)
    print(sOut)
    for childKey in node.lstChildren:
        node2 = dctNode[childKey]
        ScanNodesVerbose(node2, dctNode, indent + 4, sOut)


def StatNextGenerations(node:Node, dctNodes):
    node.childCnt = len(node.lstChildren)
    node.descendantCnt = node.childCnt
    for child in node.lstChildren:
        node.descendantCnt += StatNextGenerations(dctNodes[child], dctNodes)
    
    return node.descendantCnt
    
    return node.childCnt

from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    print('begin work')
    
    setTopNodes, dctNodes = ParseFile()
    for node in setTopNodes:
        StatNextGenerations(node, dctNodes)    
    setTopNodes = sorted(setTopNodes, key=lambda x: 1E6 - x.descendantCnt)
    for node in setTopNodes:
        ScanNodes(node, dctNodes, 0)
    indent = 0

